<?php
/**
 * Created by PhpStorm.
 * User: seven
 * Date: 2018/3/4
 * Time: 下午10:29
 *
 * MyDB::addConfig("dev", [
 *      'db' => 'mysql',
 *      'host' => 'rm-bp16ad3ce8188drq6o.mysql.rds.aliyuncs.com',
 *      'port' => '3306',
 *      'dbname' => 'app_platform',
 *      'username' => 'root',
 *      'password' => 'cowthan_777',
 * ]);
 *
 * define(DB_SINARIO, "dev");
 *
 * $db = MyDB::getInstance(DB_SINARIO);
 */

class MyDB{

    ///配置相关，静态方法=================
    private static $config = array();
    private static $current_sinario = null;

    public static function addConfig($db_sinario, array $db_config){
       self::$config[$db_sinario] = $db_config;
    }

    public static function setCurrentSinario($name){
        self::$current_sinario = $name;
    }

    static function getInstance(){
        $sinario = self::$current_sinario;
        if($sinario == null){
            throw new \Exception("数据库初始化错误，没有调用setCurrentSinario进行设置");
        }
        if(!array_key_exists($sinario, self::$config)){
            throw new \Exception("数据库初始化错误，没有找到名为{$sinario}的配置项");
        }
        $db = new MyDB(self::$config[$sinario]);
        return $db;
    }

    //=================================
    private $pdo;

    private function __construct(array $db_config){
        if($db_config["db"] == 'mysql'){
            //mysql:host=rm-bp16ad3ce8188drq6o.mysql.rds.aliyuncs.com;dbname=app_platform
            $driver = "mysql:host={$db_config['host']};dbname={$db_config['dbname']}";
//            echo $driver;
            try{
                $this->pdo = new PDO($driver, $db_config['username'], $db_config['password']);
                $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                $this->pdo -> query('SET NAMES UTF8');
            }catch (\Exception $e){
                throw $e;
            }
        }else{
            throw new \Exception("不支持的数据库：" . $db_config["db"]);
        }


    }

    //insert into imooc_admin(username, password, email) values ('king', 'b2086154f101464aab3328ba7e060deb', '279800561@qq.com')";

    /**
     * @param $table
     * @param array $contentValues
     * @return 返回刚插入的记录的的主键
     */
    public function insert($table, array $contentValues){

        $db = $this->pdo;
        $sql = "insert into `" . $table . "`({fields}) values ({values});";
        $fields = "";
        $values = "";
        foreach ($contentValues as $key => $vv){
            $fields .= "`" . $key . "`, ";
            $values .= ":" . $key . ", ";
        }
        $fields = substr($fields, 0, strlen($fields) - 2);
        $values = substr($values, 0, strlen($values) - 2);

        $sql = str_replace("{fields}", $fields, $sql);
        $sql = str_replace("{values}", $values, $sql);

//        echo $sql;

        $statement = $db->prepare($sql);
        $statement->execute($contentValues);

        return $db->lastInsertId();
    }

    public function insertSql($sql,  array $contentValues){
        $db = $this->pdo;
        $statement = $db->prepare($sql);
        $statement->execute($contentValues);
        return $db->lastInsertId();
    }

    public function updateSql($sql,  array $contentValues){
        $db = $this->pdo;
        $statement = $db->prepare($sql);
        $statement->execute($contentValues);
        return $db->rowCount();
    }

    public function deleteSql($sql,  array $contentValues){
        $db = $this->pdo;
        $statement = $db->prepare($sql);
        $statement->execute($contentValues);
        return $db->rowCount();
    }

    /**
     * @param $table
     * @param array $contentValues
     * @param $whereCondition
     * @param array $whereParams
     * @return int  返回修改的行数，有时如果没有进行实际修改，比如各个字段值都没变，会返回0
     */
    public function update($table, array $contentValues, $whereCondition, array $whereParams){

        $db = $this->pdo;
        $sql = "UPDATE " . $table . " SET {values} where 1=1";
        if($whereCondition){
            $sql .= " and " . $whereCondition . ";";
        }else{
            $sql .= ";";
        }

        $values = "";
        foreach ($contentValues as $key => $vv){
            $values .= "$key=:" . $key . ", ";
        }
        $values = substr($values, 0, strlen($values) - 2);

        $sql = str_replace("{values}", $values, $sql);

        $statement = $db->prepare($sql);
        $statement->execute(array_merge($contentValues, $whereParams));

        return $statement->rowCount();
    }


    public function delete($table, $whereCondition, array $whereParams){

        $db = $this->pdo;
        $sql = "delete from " . $table . " where 1=1";
        if($whereCondition){
            $sql .= " and " . $whereCondition . ";";
        }else{
            $sql .= ";";
        }

        $statement = $db->prepare($sql);
        $statement->execute($whereParams);

        return $statement->rowCount();
    }

    /**
     * @param $sql
     * @param $assoc_params
     * @return array  返回数组
     */
    public function findAll($sql, $assoc_params){
        $db = $this->pdo;
        $statement = $db->prepare($sql);
        $statement->execute($assoc_params);

        $res = array();
        while($row = $statement->fetch(PDO::FETCH_ASSOC)){
            $res[] = $row;
        }
        return $res;
    }


    public function findOne($sql, $assoc_params){
        $db = $this->pdo;
        $statement = $db->prepare($sql);
        $statement->execute($assoc_params);

        $row = $statement->fetch(PDO::FETCH_ASSOC);
        return $row;
    }

    public function findOneField($sql, $assoc_params){
        $db = $this->pdo;
        $statement = $db->prepare($sql);
        $statement->execute($assoc_params);

        $row = $statement->fetch(PDO::FETCH_NUM);
        if($row){
            return $row[0];
        }else{
            return null;
        }
    }


    private static function extractFields($rawArray, $fields){
        if($fields == null || count($fields) == 0) return $rawArray;

        $res = array();
        foreach ($fields as $key => $value){
            if(array_key_exists($key, $rawArray)){
                $res[$key] = $rawArray[$key];
            }else{
                $res[$key] = null;
            }
        }
        return $res;
    }
}